using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using WPFTemplateLib.WpfHelpers;

namespace WPFTemplateLib.Attached
{
	/// <summary>
	/// DataGrid 附加属性帮助类
	/// </summary>
	public class DataGridAttached
    {
        #region 是否显示行号（IsShowRowNumber）

        //https://www.cnblogs.com/luqingfei/p/12697212.html

        public static bool GetIsShowRowNumber(DependencyObject obj)
		{
			return (bool)obj.GetValue(IsShowRowNumberProperty);
		}

        /// <summary>
        /// 是否显示行号（在 Row.Header 中）
        /// </summary>
        /// <example>
        ///	<code>
        ///	{Binding Header, RelativeSource={RelativeSource AncestorType=DataGridRow}}
        /// </code>
        /// </example>
        [AttachedPropertyBrowsableForType(typeof(DataGrid))]
		public static void SetIsShowRowNumber(DependencyObject obj, bool value)
		{
			obj.SetValue(IsShowRowNumberProperty, value);
		}

		/// <summary>
		/// 设置是否显示行号
		/// </summary>
		public static readonly DependencyProperty IsShowRowNumberProperty =
			DependencyProperty.RegisterAttached("IsShowRowNumber", typeof(bool), typeof(DataGridAttached),
				new PropertyMetadata(false, OnIsShowRowNumberChanged));

		private static void OnIsShowRowNumberChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			DataGrid grid = d as DataGrid;
			if (grid == null)
			{
				return;
			}

			if ((bool)e.NewValue)
			{
				grid.LoadingRow += OnGridLoadingRow;
				grid.UnloadingRow += OnGridUnloadingRow;
			}
			else
			{
				grid.LoadingRow -= OnGridLoadingRow;
				grid.UnloadingRow -= OnGridUnloadingRow;
			}
		}

		private static void RefreshDataGridRowNumber(object sender)
		{
			DataGrid grid = sender as DataGrid;
			if (grid == null)
			{
				return;
			}

			foreach (var item in grid.Items)
			{
				var row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromItem(item);
				if (row == null)
				{
					return;
				}
				row.Header = row.GetIndex() + 1;
			}
		}

		private static void OnGridUnloadingRow(object sender, DataGridRowEventArgs e)
		{
			RefreshDataGridRowNumber(sender);
		}

		private static void OnGridLoadingRow(object sender, DataGridRowEventArgs e)
		{
			RefreshDataGridRowNumber(sender);
		}

		#endregion

		#region 不按 Ctrl/Shift 键也能多选行

		#region [附加属性] 是否支持不按修改键也能多选行
		public static bool GetIsSupportMultiSelectWithoutModifiers(DependencyObject obj)
		{
			return (bool)obj.GetValue(IsSupportMultiSelectWithoutModifiersProperty);
		}
		/// <summary>
		/// 设置 是否支持不按修改键也能多选行
		/// </summary>
		public static void SetIsSupportMultiSelectWithoutModifiers(DependencyObject obj, bool value)
		{
			obj.SetValue(IsSupportMultiSelectWithoutModifiersProperty, value);
		}
		/// <summary>
		/// [附加属性] 是否支持不按修改键也能多选行
		/// </summary>
		public static readonly DependencyProperty IsSupportMultiSelectWithoutModifiersProperty =
			DependencyProperty.RegisterAttached("IsSupportMultiSelectWithoutModifiers", typeof(bool), typeof(DataGridAttached), new PropertyMetadata(false, IsSupportMultiSelectWithoutModifiersChangedCallback));
		private static void IsSupportMultiSelectWithoutModifiersChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			DataGrid grid = d as DataGrid;
			if(grid == null)
				return;

			/*使用 PreviewMouseLeftButtonDown 会导致表格上方的 Popup 窗口操作不正常；MouseDown 会导致与 CheckBox 双向绑定的情况以及其它一些情况下无法选中；
			 已通过排除常见的可交互控件的点击解决了。*/
			if((bool)e.NewValue)
			{
				grid.PreviewMouseLeftButtonDown += DataGrid_MouseUp;
			}
			else
			{
				grid.PreviewMouseLeftButtonDown -= DataGrid_MouseUp;
			}
		}
		#endregion

		/// <summary>
		/// 让 DataGrid 不按修改键也能多选行
		/// <para/>来自：https://stackoverflow.com/a/6971358/26873826
		/// </summary>
		public static void DataGrid_MouseUp(object sender, MouseButtonEventArgs e)
		{
			DataGrid grid = sender as DataGrid;
			if (grid == null) return;

			var row = DependencyObjectExtension.TryFindFromPoint<DataGridRow>(grid, e.GetPosition(grid));
			if (row == null) return;

			// 判断是否在交互控件内
			if (e.OriginalSource is DependencyObject originalSource)
			{
				if (originalSource.TryFindParent<CheckBox>() != null ||
					originalSource.TryFindParent<Button>() != null ||
					originalSource.TryFindParent<TextBox>() != null ||
					originalSource.TryFindParent<ComboBox>() != null ||
					originalSource.TryFindParent<Hyperlink>() != null)
				{
					return;
				}
			}

			ModifierKeys mods = Keyboard.PrimaryDevice.Modifiers;
			if ((mods & ModifierKeys.Control) == 0 && (mods & ModifierKeys.Shift) == 0)
			{
				row.IsSelected = !row.IsSelected;
				e.Handled = true;
			}
		}

		#endregion

		#region 自动列生成时忽略指定的(带有特性)属性

		#region [附加属性] 是否支持自动生成列时忽略特定属性
		public static bool GetIsSupportIgnorePropWhenAutoGenerate(DependencyObject obj)
		{
			return (bool)obj.GetValue(IsSupportIgnorePropWhenAutoGenerateProperty);
		}
		/// <summary>
		/// 设置 是否支持自动生成列时忽略特定属性
		/// </summary>
		public static void SetIsSupportIgnorePropWhenAutoGenerate(DependencyObject obj, bool value)
		{
			obj.SetValue(IsSupportIgnorePropWhenAutoGenerateProperty, value);
		}
		/// <summary>
		/// [附加属性] 是否支持自动生成列时忽略特定属性
		/// </summary>
		public static readonly DependencyProperty IsSupportIgnorePropWhenAutoGenerateProperty =
			DependencyProperty.RegisterAttached("IsSupportIgnorePropWhenAutoGenerate", typeof(bool), typeof(DataGridAttached), new PropertyMetadata(false, IsSupportIgnorePropWhenAutoGenerate_ChangedCallback));
		private static void IsSupportIgnorePropWhenAutoGenerate_ChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			DataGrid grid = d as DataGrid;
			if(grid == null)
				return;

			if((bool)e.NewValue)
			{
				grid.AutoGeneratingColumn += OnAutoGeneratingColumn;
			}
			else
			{
				grid.AutoGeneratingColumn -= OnAutoGeneratingColumn;
			}
		}
		#endregion

		private static void OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
		{
			var propertyDescriptor = (PropertyDescriptor)e.PropertyDescriptor;
			if(propertyDescriptor.Attributes[typeof(ExcludeFromAutoGenerationAttribute)] != null)
			{
				e.Cancel = true;
			}
		}

		#endregion
	}

	/// <summary>
	/// 可用于 DataGrid 自动生成列时标记排除项
	/// </summary>
	[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
	public class ExcludeFromAutoGenerationAttribute : Attribute
	{
		public string Reason { get; set; }
	}
}
